home *** CD-ROM | disk | FTP | other *** search
- /*
- HEADER: CUG199.09;
- TITLE: GED (nee QED) screen editor -- part 9;
- DATE: 10/10/86;
-
- DESCRIPTION: "Virtual memory manager for GED editor. Eg. swapout,
- pageout.";
- KEYWORDS: text storage, memory management, virtual storage, paging;
- SYSTEM: MS-DOS;
- FILENAME: GED9.C;
- AUTHORS: G. Nigel Gilbert, James W. Haefner, Mel Tearle, G. Osborn;
- COMPILERS: DeSmet C;
- */
-
- /*
- e/qed/ged screen editor
-
- (C) G. Nigel Gilbert, MICROLOGY, 1981
- August-December 1981
-
- Modified: Aug-Dec 1984: BDS-C 'e'(vers 4.6a) to 'qe' (J.W. Haefner)
- March 1985: BDS-C 'qe' to DeSmet-C 'qed' (J.W. Haefner)
- May 1986: converted to ged - Mel Tearle
-
- FILE: ged9.c
-
- FUNCTIONS: initvm, freememslot, swapout, writepage,
- swappin, readpage, fatalerror
-
- PURPOSE: manages virtual memory
-
- */
-
- #include <stdio.h>
- #include "ged.h"
-
- int allo;
-
- /* Initialize virtual memory system. There are MAXSLOTS pages. The data in a given
- page may be either in RAM or in a temporary disc file. The most recently
- used data is kept in RAM. There are up to RAMSLOTS of pages in RAM.
-
- If virtslot[page] is positive then the value is the slot number in RAM
- which contains the text for that page. If negative then the disc slot
- number is -(virtslot[page] + 1).
-
- Selective use is made of 32-bit pointers. Most of the program uses 16-bit
- pointers and would be difficult and inefficient to convert to a large
- data model. Pointer arithmetic on far pointers cannot cross a 64k boundary.
- Huge pointer calculations can cross these boundaries. The use of far and
- huge pointers is controlled by the preprocessor directives in ged.h.
-
- If the page size is evenly divisible into 64 k then a page will never
- span a 64 k boundary and far pointers can be used in time critical functions.
- The far pointer arithmetic is significantly faster for far pointers and
- they are used in this version. There are also places where huge
- pointer arithmetic must be used in order to obtain correct carry
- propogation.
-
- */
- initvm()
- {
- int slot;
- unsigned int size;
- static unsigned long int lsize;
- static char HUGE * hptr = 0L;
- char HUGE * cdecl hptr1;
- int i;
- long int ll;
- char *malloc();
- char *ptr;
- char HUGE * malloc2();
- char buf[40];
- if (sizeof(*tp) != sizeof(long))
- cerr(92); /* see comments in deltp() */
-
- /* fullmem set by -M load time option */
- if (hptr == 0L) {
- lsize = (long) fullmem*1024L;
- hptr = malloc2(&lsize); /* adjusts lsize downward */
- }
- hptr1 = hptr;
- slotsinmem = lsize/PAGESIZE;
-
- if ( slotsinmem < 3 ) {
- error1( "Can't allocate enough memory" );
- xit();
- }
- allo = lsize/1024L;
- for (slot = 0; slot < slotsinmem; slot++) {
- usage[slot] = 0;
- auxloc[slot] = 0;
- slotaddr[slot] = hptr1;
- hptr1 += PAGESIZE;
- }
- for (i = 0; i < MAXSLOTS; i++) {
- virtslot[i] = 0;
- dskslots[i] = 0;
- }
-
- clock = 1;
-
- /* reserve slot 0 for an array of tp structures. Additional slots
- * will be taken later for tp if needed.
- */
- tp = (struct addr HUGE *)slotaddr[0];
- tpslots = 1;
- usage[tpslots-1] = -1;
-
- /* assign first page for line injection. */
- newpage = 0;
- virtslot[newpage] = freememslot();
- allocp = 0;
- usage[virtslot[newpage]] = MAXINT;
-
- /* paging file not yet created */
- pagefd = NOFILE;
- return;
- }
-
-
- /* Returns the number of a free memory slot, possibly by swapping out
- the least recently used page currently in memory. If that page is
- already on disc then the RAM slot is immediately reused.
- On the initial read, text is stored starting at the top of allocated
- memory and working downward. The tp array works upward from low memory.
- The portion used by tp must be contiguous. newpage is not swaped out.
- */
- int freememslot()
- {
- int use, u;
- int i, slot, nclk;
-
- nclk = 1;
- use = MAXINT;
- slot = slotsinmem-1;
- for ( i = slotsinmem-1; (use != 0) && (i >= tpslots); i-- ) {
- if ( ( u = usage[i] ) < use ) {
- use = u;
- slot = i;
- }
- }
- if ( use > 0 ) {
- swapout( slot ); /* no free slots. make one */
- }
- auxloc[slot] = 0; /* RAM slot has no disc association */
- if (!goteof)
- usage[slot] = clock++;
- return slot;
- }
-
-
- /* swaps page currently in memory at 'slot' to disk,
- * updating virtslot to show new location
- */
- swapout(slot)
- int slot;
- {
- int pg;
-
- /* find page number for ram data at 'slot' */
- for ( pg = 0; (virtslot[pg] != slot) && (pg < MAXSLOTS); pg++ )
- ;
- if(pg==MAXSLOTS)
- cerr(90); /* memory is probably clobbered */
-
- if (auxloc[slot] == 0) {
- virtslot[pg] = -writepage( slot ) - 1; /* update virtslot with disk slot written to */
- }
- else {
- virtslot[pg] = auxloc[slot]; /* page already exists on disc */
- auxloc[slot] = 0; /* RAM slot will lose its disc association with this record */
- }
- usage[slot] = 0; /* the ram slot is free */
- return;
- }
-
-
- /* Writes page currently in memory at 'slot' to disk.
- * Returns disk slot where written. Locations near the beginning
- * of the file are used when available to miminize total file size.
- */
- writepage(slot)
- int slot;
- {
- int i;
- unsigned loc;
- long int sekbytes;
- long int lseek1();
-
- long int dbuf[PAGESIZE/sizeof(long)];
- long int *pt1;
- long int FAR *pt2;
-
-
- if ( pagefd == NOFILE ) { /* haven't opened paging file yet */
-
- if ( (pagefd = creatb(pagingfile)) == FAIL )
- fatalerror( " Can't create a buffer file" );
- for ( loc = 0; loc < MAXSLOTS; loc++ )
- dskslots[loc] = 0;
- }
-
- for ( loc = 0; dskslots[loc] != 0; loc++ ) /* find a free slot */
- ;
- if (loc >= MAXSLOTS)
- cerr(93); /* table corrupt */
- sekbytes = (long) loc*PAGESIZE;
-
- if ( lseek1( pagefd, sekbytes) == -1L )
- fatalerror(" Bad seek in writing buffer ");
-
- /* move far data to near data */
- pt2 = (long int FAR *) slotaddr[slot];
- pt1 = &dbuf[0];
- for (i = 1; i <= PAGESIZE/sizeof(long); i++)
- *pt1++ = *pt2++;
-
- if ( write( pagefd, dbuf, PAGESIZE ) == FAIL )
- fatalerror(" Can't write to buffer - disk full " );
- dskslots[loc] = 1;
- usage[slot] = 0;
- return loc;
- }
-
-
- /* get 'page', currently on disk,
- * into memory and return slot where placed
- * the disc location is saved in auxloc in case the page needs to be
- * rolled out again without change.
- *
- * The priority is set to 1 when read. If read for a global string search
- * the priority stays at the lowest priority and the same memory slot will
- * be used for the next page. The established page priority is therefore
- * mostly unaffected by global searches. If loaded for gettext() the
- * priority will immediately be raised to 'clock' and the page will
- * usually stay resident for a long time.
- */
- swappin(page)
- int page;
- {
- int slot, dslot;
- int i;
- if(virtslot[page] >= 0)
- cerr(91); /* table corrupt */
- slot = freememslot();
- readpage( slot, -1 -virtslot[page] );
- usage[slot] = 1;
- auxloc[slot] = virtslot[page]; /* remember where it came from */
- virtslot[page] = slot;
- return slot;
- }
-
-
- /* read a page from disk into
- * memory at 'memsl'
- */
- readpage(memsl,dskslot)
- int memsl, dskslot;
- {
- long sekbytes;
- int i;
- long int *pt1;
- long int FAR *pt2;
- long int dbuf[PAGESIZE/sizeof(long)];
- char buf[80];
- long int lseek1();
-
- sekbytes = (long) dskslot*PAGESIZE;
- if ( lseek1( pagefd, sekbytes ) == -1L )
- fatalerror(" Bad seek in reading buffer ");
- i=read( pagefd, dbuf, PAGESIZE );
- if ( i != PAGESIZE )
- fatalerror(" Can't read disc buffer ");
-
- /* move near data to far data */
- pt2 = (long int FAR *) slotaddr[memsl];
- pt1 = &dbuf[0];
- for (i = 1; i <= PAGESIZE/sizeof(long); i++)
- *pt2++ = *pt1++;
-
- return;
- }
-
-
- /* displays message, returns to a
- * known good screen
- */
- fatalerror(message)
- char *message;
- {
- error( message );
- moveline( goodline-cline );
- longjmp( 0, 1 );
- }
-
- /* There are two pools from which memory is allocated when
- using the Microsoft compiler ver 4.00. Choose the larger of the two.
- */
- char HUGE *malloc2(amnt)
- unsigned long int *amnt;
- {
- char HUGE *halloc();
- char HUGE *hptr1;
- char *ptr;
- unsigned long int hsize,ssize;
- unsigned int isize;
-
- ssize = hsize = *amnt+PAGESIZE;
-
- /* halloc always returns a pointer with an offset of 0. That is required
- * in order to avoid lines crossing a 64 k boundary. The call to
- * malloc below does not return a 0 offset, but the entire data space
- * in that case is within the span of the DS register so no element
- * anywhere will cross a 64 k boundary.
- */
- do {
- hsize -= PAGESIZE;
- hptr1 = halloc(hsize,1L);
- }
- while ( (hptr1 == 0L) && (hsize > 0L) );
-
- do {
- ssize -= PAGESIZE;
- if (ssize < 0x10000L)
- ptr = malloc(isize = ssize);
- else
- ptr = 0;
- }
- while ( ( ptr == 0) && (ssize > 0L) );
-
- /* give back the small one unless the small one satisfies the -M option */
- if (hsize > ssize && ssize < *amnt ) {
- free(ptr);
- *amnt = hsize;
- return hptr1;
- }
- else {
- hfree(hptr1);
- *amnt = ssize;
- return (char HUGE *) ptr;
- }
- }
- putallo()
- {
- char buf[50];
- sprintf(buf,"%d kb allocated ",allo);
- scr_aputs(43,0,buf,ATTR3);
- return;
- }
-
-
-
-
-
-